using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using MEA.AE_Data.Access;
using MEA.AE_Data.Config;

namespace MEA.AE_BusinessLogic
{
	public abstract class RecManBase : IDisposable
	{
		public class CInDumpData
		{
			public ConfigData.e_ECUID ecu;

			public ConfigData.EHexDumpProc thProcType;

			public string logPath;

			public int blckCnt;

			public List<int> sectorsNrList;

			public RecManStatus recManStatus;

			public Thread myThread;

			public void setCInDumpData(CInDumpData x)
			{
				logPath = x.logPath;
				sectorsNrList = x.sectorsNrList;
				blckCnt = x.blckCnt;
				thProcType = x.thProcType;
			}
		}

		public class RecManSector : IComparable
		{
			private int id;

			private List<byte> dataPayld;

			private List<byte> dataRaw;

			private RecManSector_Type type;

			private bool chkOk;

			public bool ChkOk
			{
				get
				{
					return chkOk;
				}
			}

			public List<byte> DataPayld
			{
				get
				{
					return dataPayld;
				}
			}

			public List<byte> DataRaw
			{
				get
				{
					return dataRaw;
				}
			}

			public int ID
			{
				get
				{
					return id;
				}
			}

			public RecManSector_Type Type
			{
				get
				{
					return type;
				}
			}

			public RecManSector(int id, ref List<byte> dataRaw, bool readwrite)
			{
				this.id = id;
				byte[] code = new byte[4];
				chkOk = true;
				if (readwrite)
				{
					uint num = 0u;
					dataPayld = dataRaw.GetRange(2, dataRaw.Count - 10);
					this.dataRaw = dataRaw;
					code[0] = dataRaw[dataRaw.Count - 1];
					code[1] = dataRaw[dataRaw.Count - 2];
					code[2] = dataRaw[dataRaw.Count - 3];
					code[3] = dataRaw[dataRaw.Count - 4];
					type = RecManSector_Type.unknown;
					DecodeSectorType(ref code);
					if (type == RecManSector_Type.locked)
					{
						uint num2 = num;
						for (int i = 2; i < this.dataRaw.Count - 4; i += 4)
						{
							num2 += num;
							num = this.dataRaw[i];
							num <<= 8;
							num += this.dataRaw[i + 1];
							num <<= 8;
							num += this.dataRaw[i + 2];
							num <<= 8;
							num += this.dataRaw[i + 3];
						}
						if (num != num2)
						{
							chkOk = false;
						}
					}
				}
				else
				{
					this.dataRaw = new List<byte>();
					this.dataRaw.AddRange(dataRaw);
					code[0] = dataRaw[dataRaw.Count - 1];
					code[1] = dataRaw[dataRaw.Count - 2];
					code[2] = dataRaw[dataRaw.Count - 3];
					code[3] = dataRaw[dataRaw.Count - 4];
					DecodeSectorType(ref code);
				}
			}

			public void Print(StreamWriter writer)
			{
				writer.WriteLine("Sector " + ID);
				int i = 0;
				try
				{
					for (; i < DataRaw.Count; i++)
					{
						if (i % 8 == 0)
						{
							writer.WriteLine();
						}
						writer.Write(string.Format("{0:X2}", dataRaw[i]) + ";");
					}
				}
				catch
				{
				}
				writer.WriteLine();
			}

			public void WriteToFile(object filepath)
			{
				throw new NotImplementedException();
			}

			private void DecodeSectorType(ref byte[] code)
			{
				type = RecManSector_Type.unknown;
				switch (code[0])
				{
				case byte.MaxValue:
					if (code[1] == byte.MaxValue && code[2] == byte.MaxValue && code[3] == byte.MaxValue)
					{
						type = RecManSector_Type.notModified;
					}
					break;
				case 254:
					if (code[1] == 254 && code[2] == 254 && code[3] == 254)
					{
						type = RecManSector_Type.erased;
					}
					break;
				case 170:
					if (code[1] == 170 && code[2] == 170 && code[3] == 170)
					{
						type = RecManSector_Type.active;
					}
					break;
				case 168:
					if (code[1] == 168 && code[2] == 168 && code[3] == 168)
					{
						type = RecManSector_Type.fullNotLocked;
					}
					break;
				case 0:
					if (code[1] == 0 && code[2] == 0 && code[3] == 0)
					{
						type = RecManSector_Type.locked;
					}
					break;
				}
			}

			public int CompareTo(object obj)
			{
				if (obj is RecManSector)
				{
					RecManSector recManSector = (RecManSector)obj;
					return id.CompareTo(recManSector.ID);
				}
				throw new ArgumentException("object is not a RecManSector");
			}
		}

		protected const int LastEventRecAdressBereichI = 15;

		protected const int LastDataLoggerAdressBereich = 139;

		protected const int LastAdressBereich = 155;

		public const int AllAddressFlashArea = 156;

		public const int DataLogFlashAreaCnt = 140;

		public const int DataLogEventRecAreaCnt = 15;

		protected BaseService baseService;

		protected UIGraphWindow grLayer;

		protected int activeSector;

		protected int currentSector;

		public List<RecManSector> sectorsRaw_AL;

		protected Form UIWindow;

		protected ConfigData.e_ECUID AB;

		protected List<byte> dataPayload;

		protected List<byte> send_AL;

		protected object[] recordItem_LUT;

		protected static int[,] AdressBereiche = new int[156, 2]
		{
			{ 268435456, 268443647 },
			{ 272629760, 272637951 },
			{ 268443648, 268451839 },
			{ 272637952, 272646143 },
			{ 268451840, 268460031 },
			{ 272646144, 272654335 },
			{ 268460032, 268468223 },
			{ 272654336, 272662527 },
			{ 268468224, 268476415 },
			{ 272662528, 272670719 },
			{ 268476416, 268484607 },
			{ 272670720, 272678911 },
			{ 268484608, 268492799 },
			{ 272678912, 272687103 },
			{ 268492800, 268500991 },
			{ 272687104, 272695295 },
			{ 268500992, 268566527 },
			{ 272695296, 272760831 },
			{ 268566528, 268632063 },
			{ 272760832, 272826367 },
			{ 268632064, 268697599 },
			{ 272826368, 272891903 },
			{ 268697600, 268763135 },
			{ 272891904, 272957439 },
			{ 268763136, 268828671 },
			{ 272957440, 273022975 },
			{ 268828672, 268894207 },
			{ 273022976, 273088511 },
			{ 268894208, 268959743 },
			{ 273088512, 273154047 },
			{ 268959744, 269025279 },
			{ 273154048, 273219583 },
			{ 269025280, 269090815 },
			{ 273219584, 273285119 },
			{ 269090816, 269156351 },
			{ 273285120, 273350655 },
			{ 269156352, 269221887 },
			{ 273350656, 273416191 },
			{ 269221888, 269287423 },
			{ 273416192, 273481727 },
			{ 269287424, 269352959 },
			{ 273481728, 273547263 },
			{ 269352960, 269418495 },
			{ 273547264, 273612799 },
			{ 269418496, 269484031 },
			{ 273612800, 273678335 },
			{ 269484032, 269549567 },
			{ 273678336, 273743871 },
			{ 269549568, 269615103 },
			{ 273743872, 273809407 },
			{ 269615104, 269680639 },
			{ 273809408, 273874943 },
			{ 269680640, 269746175 },
			{ 273874944, 273940479 },
			{ 269746176, 269811711 },
			{ 273940480, 274006015 },
			{ 269811712, 269877247 },
			{ 274006016, 274071551 },
			{ 269877248, 269942783 },
			{ 274071552, 274137087 },
			{ 269942784, 270008319 },
			{ 274137088, 274202623 },
			{ 270008320, 270073855 },
			{ 274202624, 274268159 },
			{ 270073856, 270139391 },
			{ 274268160, 274333695 },
			{ 270139392, 270204927 },
			{ 274333696, 274399231 },
			{ 270204928, 270270463 },
			{ 274399232, 274464767 },
			{ 270270464, 270335999 },
			{ 274464768, 274530303 },
			{ 270336000, 270401535 },
			{ 274530304, 274595839 },
			{ 270401536, 270467071 },
			{ 274595840, 274661375 },
			{ 270467072, 270532607 },
			{ 274661376, 274726911 },
			{ 270532608, 270598143 },
			{ 274726912, 274792447 },
			{ 270598144, 270663679 },
			{ 274792448, 274857983 },
			{ 270663680, 270729215 },
			{ 274857984, 274923519 },
			{ 270729216, 270794751 },
			{ 274923520, 274989055 },
			{ 270794752, 270860287 },
			{ 274989056, 275054591 },
			{ 270860288, 270925823 },
			{ 275054592, 275120127 },
			{ 270925824, 270991359 },
			{ 275120128, 275185663 },
			{ 270991360, 271056895 },
			{ 275185664, 275251199 },
			{ 271056896, 271122431 },
			{ 275251200, 275316735 },
			{ 271122432, 271187967 },
			{ 275316736, 275382271 },
			{ 271187968, 271253503 },
			{ 275382272, 275447807 },
			{ 271253504, 271319039 },
			{ 275447808, 275513343 },
			{ 271319040, 271384575 },
			{ 275513344, 275578879 },
			{ 271384576, 271450111 },
			{ 275578880, 275644415 },
			{ 271450112, 271515647 },
			{ 275644416, 275709951 },
			{ 271515648, 271581183 },
			{ 275709952, 275775487 },
			{ 271581184, 271646719 },
			{ 275775488, 275841023 },
			{ 271646720, 271712255 },
			{ 275841024, 275906559 },
			{ 271712256, 271777791 },
			{ 275906560, 275972095 },
			{ 271777792, 271843327 },
			{ 275972096, 276037631 },
			{ 271843328, 271908863 },
			{ 276037632, 276103167 },
			{ 271908864, 271974399 },
			{ 276103168, 276168703 },
			{ 271974400, 272039935 },
			{ 276168704, 276234239 },
			{ 272039936, 272105471 },
			{ 276234240, 276299775 },
			{ 272105472, 272171007 },
			{ 276299776, 276365311 },
			{ 272171008, 272236543 },
			{ 276365312, 276430847 },
			{ 272236544, 272302079 },
			{ 276430848, 276496383 },
			{ 272302080, 272367615 },
			{ 276496384, 276561919 },
			{ 272367616, 272433151 },
			{ 276561920, 276627455 },
			{ 272433152, 272498687 },
			{ 276627456, 276692991 },
			{ 272498688, 272564223 },
			{ 276692992, 276758527 },
			{ 272564224, 272572415 },
			{ 276758528, 276766719 },
			{ 272572416, 272580607 },
			{ 276766720, 276774911 },
			{ 272580608, 272588799 },
			{ 276774912, 276783103 },
			{ 272588800, 272596991 },
			{ 276783104, 276791295 },
			{ 272596992, 272605183 },
			{ 276791296, 276799487 },
			{ 272605184, 272613375 },
			{ 276799488, 276807679 },
			{ 272613376, 272621567 },
			{ 276807680, 276815871 },
			{ 272621568, 272629759 },
			{ 276815872, 276824063 }
		};

		public CInDumpData RecManInData = new CInDumpData();

		public event BaseService.AddConsoleHandler ev_AddConsole;

		public event EventHandler<ServiceLayerStringEventArg> ev_ProgressStep;

		public event EventHandler<ServiceLayerBoolEventArg> ev_ProgressClose;

		public event EventHandler ev_UpdateData;

		public RecManBase()
		{
			send_AL = new List<byte>();
			dataPayload = new List<byte>();
			currentSector = 0;
			activeSector = 0;
			sectorsRaw_AL = new List<RecManSector>();
		}

		protected void SortSectorsRingBuffer(ref List<RecManSector> items, int index_active)
		{
			if (index_active < items.Count - 1)
			{
				int count = items.Count - 1 - index_active;
				List<RecManSector> range = items.GetRange(index_active + 1, count);
				items.RemoveRange(index_active + 1, count);
				items.InsertRange(0, range);
			}
		}

		protected List<byte> ReadSector(int start, int end, int responseLength)
		{
			List<byte> list = new List<byte>();
			baseService.TesterPresentHalt();
			string aB = string.Format("ECU {0}:  ", AB);
			Ev_AddConsole_call(string.Format("Reading RecMan sector {0}", currentSector), Color.Black, aB);
			send_AL.Clear();
			send_AL.Add((byte)((start >> 24) & 0xFF));
			send_AL.Add((byte)((start >> 16) & 0xFF));
			send_AL.Add((byte)((start >> 8) & 0xFF));
			send_AL.Add((byte)(start & 0xFF));
			send_AL.Add((byte)((end >> 24) & 0xFF));
			send_AL.Add((byte)((end >> 16) & 0xFF));
			send_AL.Add((byte)((end >> 8) & 0xFF));
			send_AL.Add((byte)(end & 0xFF));
			send_AL.Add(0);
			send_AL.Add(0);
			send_AL.Add(0);
			send_AL.Add((byte)responseLength);
			list = baseService.AuxService(ConfigKWP.e_kwpServices.RecManSector_Read, send_AL);
			Ev_AddConsole_call(string.Format("Sector {0} read out", currentSector), Color.Black, aB);
			return list;
		}

		public abstract void SaveToXML(object file);

		public RecManStatus RecordManagerStatus()
		{
			List<byte> list = new List<byte>();
			RecManStatus result = null;
			baseService.TesterPresentHalt();
			baseService.SecuritySeedKey(1);
			baseService.Diagnose_stop();
			baseService.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
			Ev_AddConsole_call("RecordManagerStatus ..", Color.Black, string.Concat("ECU ", AB, ":  "));
			send_AL.Clear();
			try
			{
				list = baseService.AuxService(ConfigKWP.e_kwpServices.RecManStatus_Read, send_AL);
				int num = list[2] << 8;
				num |= list[3];
				activeSector = list[4];
				Ev_AddConsole_call("RecordManagerStatus: Success", Color.Black, string.Concat("ECU ", AB, ":  "));
				Ev_AddConsole_call(string.Format("Event recorder entry counter: {0:x2}", num), Color.Black, string.Concat("ECU ", AB, ":  "));
				Ev_AddConsole_call(string.Format("Active RecManSector number for the event recorder: {0:x2}", list[4]), Color.Black, string.Concat("ECU ", AB, ":  "));
				Ev_AddConsole_call(string.Format("Active RecManSector number for the datalogger: {0:x2}", list[5]), Color.Black, string.Concat("ECU ", AB, ":  "));
				result = new RecManStatus(num, list[4], list[5]);
			}
			catch (ECUSendErrorException)
			{
				Ev_AddConsole_call("RecordManagerStatus : Unable to send request", Color.Black, string.Concat("ECU ", AB, ":  "));
				baseService.TesterPresentStart(ConfigData.TesterPresentPeriod_ms);
				return result;
			}
			catch (ECUResponseTimeoutException)
			{
				Ev_AddConsole_call("Timeout error", Color.Black, string.Concat("ECU ", AB, ":  "));
				return result;
			}
			catch (ECUResponseNegativeException ex3)
			{
				baseService.ErrorReportNegResponse(Convert.ToByte(ex3.Message));
			}
			catch (ECUResponseUnkownException)
			{
				Ev_AddConsole_call("Unknown Response", Color.Black, string.Concat("ECU ", AB, ":  "));
			}
			catch (ECUDisconnectedExeption)
			{
			}
			baseService.TesterPresentStart(ConfigData.TesterPresentPeriod_ms);
			return result;
		}

		protected abstract void DecodeData();

		protected abstract void AddToGraph();

		protected abstract void InitializeRecordItems();

		protected void Ev_AddConsole_call(string s, Color c, string AB)
		{
			if (this.ev_AddConsole != null)
			{
				this.ev_AddConsole(s, c, AB);
			}
		}

		protected void Ev_UpdateData_call()
		{
			if (this.ev_UpdateData != null)
			{
				this.ev_UpdateData(this, null);
			}
		}

		protected void Ev_ProgressStep_call(object step)
		{
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(step));
			}
		}

		protected void Ev_ProgressClose_call()
		{
			if (this.ev_ProgressClose != null)
			{
				this.ev_ProgressClose(this, new ServiceLayerBoolEventArg(false));
			}
		}

		public abstract void ViewFromHexDump(ref List<RecManSector> sectors, RecManStatus status, string fileCreation);

		public void HexDumpStart()
		{
			if (RecManInData == null)
			{
				RecManInData = new CInDumpData();
			}
			RecManInData.ecu = AB;
			RecManInData.myThread = new Thread(HexDumpRun);
			RecManInData.myThread.Name = string.Format("HexDump_{0}", AB);
			RecManInData.myThread.Priority = ThreadPriority.AboveNormal;
			RecManInData.myThread.Start();
		}

		private void HexDumpRun()
		{
			RecManInData.recManStatus = RecordManagerStatus();
			if (RecManInData.recManStatus != null)
			{
				switch (RecManInData.thProcType)
				{
				case ConfigData.EHexDumpProc.eReadDatLogHours:
				case ConfigData.EHexDumpProc.eReadDatLogAll:
				{
					RecManInData.sectorsNrList = new List<int>(RecManInData.blckCnt);
					sectorsRaw_AL.Clear();
					int num = RecManInData.recManStatus.ActiveDatLog;
					RecManInData.sectorsNrList.Add(num);
					for (int j = 1; j < RecManInData.blckCnt; j++)
					{
						num--;
						if (num == RecManInData.recManStatus.ActiveDatLog)
						{
							break;
						}
						if (num == 15)
						{
							num = 139;
						}
						RecManInData.sectorsNrList.Add(num);
					}
					break;
				}
				case ConfigData.EHexDumpProc.eReadEventsAll:
				{
					RecManInData.sectorsNrList = new List<int>(RecManInData.blckCnt);
					sectorsRaw_AL.Clear();
					int num = RecManInData.recManStatus.ActiveEvRec;
					RecManInData.sectorsNrList.Add(num);
					for (int i = 1; i < RecManInData.blckCnt; i++)
					{
						num--;
						if (num < 0)
						{
							num = 155;
						}
						else if (num == 139)
						{
							num = 15;
						}
						RecManInData.sectorsNrList.Add(num);
					}
					break;
				}
				case ConfigData.EHexDumpProc.eHexDumpProc:
					sectorsRaw_AL.Clear();
					break;
				}
			}
			if (RecManInData.sectorsNrList.Count > 0)
			{
				ReadHexDumpFromECU();
			}
		}

		private void ReadHexDumpFromECU()
		{
			List<byte> dataRaw = new List<byte>(65539);
			int num = 0;
			bool flag = true;
			ConfigData.SUIProgressbar sUIProgressbar = new ConfigData.SUIProgressbar();
			baseService.SecuritySeedKey(1);
			baseService.Diagnose_stop();
			baseService.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.MemoryAccess));
			for (int i = 0; i < RecManInData.sectorsNrList.Count; i++)
			{
				if (!flag)
				{
					break;
				}
				currentSector = RecManInData.sectorsNrList[i];
				dataRaw.Clear();
				num = 0;
				sUIProgressbar.msg = string.Format("Read sector {0} from ECU {1}", currentSector, AB);
				sUIProgressbar.ecuId = AB;
				Ev_ProgressStep_call(sUIProgressbar);
				Console.WriteLine("currentsector = {0}", currentSector);
				for (; flag; num++)
				{
					if (num > ConfigData.ConnectAttempts)
					{
						baseService.TesterPresentStart(ConfigData.TesterPresentPeriod_ms);
						throw new ServiceAbortExeption("Sector " + currentSector + " could not be read.");
					}
					try
					{
						dataRaw = ReadSector(AdressBereiche[currentSector, 0], AdressBereiche[currentSector, 1], 224);
					}
					catch (ECUSendErrorException)
					{
						Ev_AddConsole_call("Read Memory: Unable to send request", Color.Black, string.Concat("ECU ", AB, ":  "));
						baseService.TesterPresentStart(ConfigData.TesterPresentPeriod_ms);
						continue;
					}
					catch (ECUResponseTimeoutException)
					{
						Ev_AddConsole_call("Timeout error", Color.Black, string.Concat("ECU ", AB, ":  "));
						continue;
					}
					catch (ECUResponseNegativeException ex3)
					{
						baseService.ErrorReportNegResponse(Convert.ToByte(ex3.Message));
						continue;
					}
					catch (ECUResponseUnkownException)
					{
						Ev_AddConsole_call("Unknown Response", Color.Black, string.Concat("ECU ", AB, ":  "));
						continue;
					}
					catch (ECUDisconnectedExeption)
					{
						baseService.TesterPresentStart(ConfigData.TesterPresentPeriod_ms);
						throw new ServiceAbortExeption("Sector " + currentSector + " could not be read. ECU disconnected!");
					}
					break;
				}
				if (dataRaw[0] == 97 && (dataRaw.Count == 65538 || dataRaw.Count == 8194))
				{
					RecManSector recManSector = new RecManSector(currentSector, ref dataRaw, false);
					if (RecManInData.thProcType != ConfigData.EHexDumpProc.eHexDumpProc && recManSector.Type == RecManSector_Type.notModified)
					{
						flag = false;
					}
					sectorsRaw_AL.Add(recManSector);
					Console.WriteLine("sectorsRaw_AL.Count = {0}", sectorsRaw_AL.Count);
				}
			}
			if (sectorsRaw_AL != null)
			{
				sectorsRaw_AL.Sort();
			}
		}

		public void Dispose()
		{
			sectorsRaw_AL.Clear();
			sectorsRaw_AL.TrimExcess();
			sectorsRaw_AL = null;
			dataPayload.Clear();
			dataPayload.TrimExcess();
			dataPayload = null;
		}
	}
}
